﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Cms.Application.WebFramework.Views;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.Comparers;
using Cms.Domain.RepositoryInterfaces;

namespace Cms.Application.WebFramework.Presenters
{
    public class RssHandlerPresenter : BasePresenter
    {
        private readonly IRssHandlerView _view;
        private User _user;
        private RssFeed _feed;
        private DateTime? _lastBuildDate;

        public RssHandlerPresenter(IRssHandlerView view)
            : this(view, new RepositoryFactory())
        {
        }

        public RssHandlerPresenter(IRssHandlerView view, IRepositoryFactory repositoryFactory)
            : base(repositoryFactory)
        {
            _view = view;
        }

        public string GetRssFeedXml()
        {
            _feed = ContentRepository.GetRssFeed(_view.Site.ID, _view.Filename);
            if (_feed == null)
            {
                return string.Empty;
            }
            IEnumerable<XElement> items = CreateElements();
            XDocument rss = new XDocument(
                                    new XDeclaration("1.0", "utf-8", "yes"),
                                    new XElement("rss",
                                        new XAttribute("version", "2.0"),
                                        new XElement("channel",
                                            new XElement("title", _feed.Name),
                                            new XElement("link", "http://" + _feed.Site.Domain),
                                            new XElement("description", _feed.Description),
                                            new XElement("language", _view.Locale.CultureCode),
                                            new XElement("lastBuildDate", (_lastBuildDate.HasValue ? _lastBuildDate.Value.ToString("r") : "")),
                                            items)
                                       ));
            return rss.ToString();
        }

        private IEnumerable<XElement> CreateElements()
        {
            IList<XElement> list = new List<XElement>();
            foreach (RssFeedEntry entry in GetEntries())
            {
                XElement itemElement = new XElement("item",
                                            new XElement("title", entry.Title),
                                            new XElement("link", entry.Link),
                                            new XElement("description", entry.Description),
                                            new XElement("pubDate", entry.PubDate)
                                       );
                list.Add(itemElement);
            }
            return list;
        }

        private IEnumerable<RssFeedEntry> GetEntries()
        {
            var categoryIDs = new List<int>();
            foreach (Category category in _feed.Categories)
            {
                categoryIDs.AddRange(category.GetAllIDs());
            }
            var filter = new SearchContentFilter(string.Empty)
                             {
                                 LocaleId = _view.Locale.ID,
                                 SortMode = _feed.SortMode,
                                 SortDirection = SortDirection.Descending
                             };
            var entries = new List<RssFeedEntry>();
            foreach (Content content in ContentRepository.ListContent(filter, 0, 100, categoryIDs))
            {
                RssFeedEntry entry = new RssFeedEntry { Title = content.GetPublishedTitle(_view.Locale.ID) };
                if (entry.Title == string.Empty)
                {
                    entry.Title = content.Name;
                }
                string html = content.GetPublishedHtml(_view.Locale.ID);
                html = Content.ReplaceVirtualUrlsWithAbsoluteUrls(html, _view.Site);
                if (_feed.ContentDisplayMode == RssFeedContentDisplayMode.Truncated)
                {
                    html = Content.TruncateAfterPageBreak(html);
                }
                if (_feed.RemoveImgTags)
                {
                    html = Content.RemoveImgTags(html);
                }
                entry.Description = html;
                if (content.Pages.Count > 0)
                {
                    entry.Link = "http://" + _feed.Site.Domain + "/" + content.Pages[0].Page.GetVirtualPath();
                }
                else
                {
                    entry.Link = "http://" + _feed.Site.Domain + "/" + _feed.ContentDisplayPage.GetVirtualPath() + "?ContentID=" + content.ID;
                }
                var contentTranslation = content.GetTranslation(_view.Locale.ID);
                if (contentTranslation.LatestPublished.HasValue)
                {
                    if (_feed.SortMode == ContentSortMode.PublishedTimestamp)
                    {
                        // Only set PubDate when using PublishedTimestamp, otherwise the feed reader will ignore the sorting dictated by SortKey 
                        entry.PubDate = contentTranslation.LatestPublished.Value.ToUniversalTime().ToString("r");
                    }
                    if (!_lastBuildDate.HasValue || _lastBuildDate.Value < contentTranslation.LatestPublished.Value.ToUniversalTime())
                    {
                        _lastBuildDate = contentTranslation.LatestPublished.Value.ToUniversalTime();
                    }
                }
                entries.Add(entry);
            }
            return entries;
        }
    }
}